import * as THREE from "three"

const buildFace = e => {
  for (const t of e)
    if (t.face)
      return {
        point: t.point,
        object: t.object,
        distance: t.distance,
        face: t.face
      }
  return null
}
const sortDistance = (e, t) => e.distance - t.distance
const n = (e, t, n) => {
  const s = e.slice().sort(sortDistance)
  const r = [s[0]]
  let o
  for (o = 1; o < s.length && r.length < 3; ++o) {
    const e = s[o]
    if (e.face) {
      const i = Math.abs(t[o].direction.dot(e.face.normal))
      r[0].point.distanceTo(e.point) * i > n && (r.length = 0)
      r.push(e)
    }
  }
  return r.length < 3 ? null : r
}
const CENTER_FIRST = (e, i) =>
  i && i.face
    ? {
        point: i.point,
        normal: i.face.normal,
        object: i.object,
        distance: i.distance,
        face: i.face
      }
    : buildFace(e)
const CLOSEST = e => buildFace(e.sort(sortDistance))
const AVERAGE = e => {
  if (0 === e.length) return null
  const t = {
    point: new THREE.Vector3(),
    face: {
      a: 0,
      b: 1,
      c: 2,
      normal: new THREE.Vector3(),
      materialIndex: 0
    },
    distance: 0,
    object: e[0].object
  }
  for (const i of e) {
    t.face && i.face && (t.point.add(i.point), t.face.normal.add(i.face.normal))
  }
  t.point.divideScalar(e.length)
  t.face && t.face.normal.divideScalar(e.length).normalize()
  return t
}

const CENTER_GROUP = t => (i, s, r) => {
  if (s) {
    const n = [s]
    for (let e = 1; e < i.length && e < 3; ++e) {
      const o = i[e]
      if (o.face) {
        const i = Math.abs(r[e].direction.dot(o.face.normal))
        s.point.distanceTo(o.point) * i <= t && n.push(o)
      }
    }
    if (n.length >= 3) {
      const t = AVERAGE(n)
      if (t && t.face && s.face) return (t.face.normal = s.face.normal), t
    }
  }
  const o = n(i, r, t)
  return o ? AVERAGE(o) : CENTER_FIRST(i, s)
}

export default {
  CENTER_FIRST,
  CLOSEST,
  AVERAGE,
  CENTER_GROUP
}
